Avage Pandase potentsiaal kohandatud funktsioonidega. Juhend selgitab apply(), map() ja applymap() erinevusi, jõudlust ja kasutusviise andmeanalüüsis.
Pandase valdamine: Sügavuti kohandatud funktsioonidega apply(), map() ja applymap() abil
Andmeteaduse ja -analüüsi maailmas on Pythoni Pandase teek asendamatu tööriist. See pakub võimsaid, paindlikke ja tõhusaid andmestruktuure, mis on loodud struktureeritud andmetega töötamise lihtsaks ja intuitiivseks muutmiseks. Kuigi Pandas on varustatud rikkaliku sisseehitatud funktsioonide komplektiga agregeerimiseks, filtreerimiseks ja teisendamiseks, jõuab iga andmespetsialisti teekonnal kätte aeg, mil neist ei piisa. Peate rakendama oma kohandatud loogikat, unikaalset ärinõuet või keerulist teisendust, mis pole koheselt saadaval.Siin muutub kohandatud funktsioonide rakendamise võime supervõimeks. Pandas pakub selle saavutamiseks aga mitmeid viise, peamiselt meetodite apply(), map() ja applymap() kaudu. Uustulnukale võivad need funktsioonid tunduda eksitavalt sarnased. Millist peaksite kasutama? Millal? Ja millised on teie valiku jõudlusmõjud?
See põhjalik juhend demüstifitseerib need võimsad meetodid. Uurime igaüht neist üksikasjalikult, mõistame nende spetsiifilisi kasutusjuhtumeid ja, mis kõige tähtsam, õpime, kuidas valida töö jaoks õige tööriist puhta, tõhusa ja loetava Pandase koodi kirjutamiseks. Käsitleme:
- Meetod
map(): Ideaalne elemendipõhiseks teisenduseks ühel seerias (Series). - Meetod
apply(): Mitmekülgne tööhobune reahaaval või veerupõhiseks tegevuseks andmeraamistikus (DataFrame). - Meetod
applymap(): Spetsialist elemendipõhiseks tegevuseks kogu andmeraamistikus (DataFrame). - Jõudluskaalutlused: Kriitiline erinevus nende meetodite ja tõelise vektoriseerimise vahel.
- Parimad tavad: Otsustusraamistik, mis aitab teil iga kord valida kõige tõhusama meetodi.
Lava seadistamine: Meie näidisandmestik
Et muuta meie näited praktiliseks ja selgeks, kasutame ühtset, globaalselt olulist andmestikku. Loome näidis-DataFrame'i, mis esindab väljamõeldud rahvusvahelise e-kaubanduse ettevõtte veebimüügi andmeid.
import pandas as pd
import numpy as np
data = {
'OrderID': [1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008],
'Product': ['Laptop', 'Mouse', 'Keyboard', 'Monitor', 'Webcam', 'Headphones', 'Docking Station', 'Mouse'],
'Category': ['Electronics', 'Accessories', 'Accessories', 'Electronics', 'Accessories', 'Audio', 'Electronics', 'Accessories'],
'Price_USD': [1200, 25, 75, 300, 50, 150, 250, 30],
'Quantity': [1, 2, 1, 2, 1, 1, 1, 3],
'Country': ['USA', 'Canada', 'USA', 'Germany', 'Japan', 'Canada', 'Germany', np.nan]
}
df = pd.DataFrame(data)
print(df)
See DataFrame annab meile hea segu andmetüüpidest (numbrilised, stringid ja isegi puuduv väärtus), et demonstreerida meie sihtfunktsioonide täielikke võimalusi.
Meetod map(): Elemendipõhine teisendus seeria (Series) jaoks
Mis on map()?
Meetod map() on teie spetsialiseeritud tööriist väärtuste muutmiseks ühes veerus (Pandase Series). See töötab elemendipõhiselt. Mõelge sellele kui ütlusele: "Iga selles veerus oleva elemendi puhul otsige see üles sõnastikust või laske see läbi selle funktsiooni ja asendage tulemusega."
Seda kasutatakse peamiselt kahe ülesande jaoks:
- Väärtuste asendamine sõnastiku (vastenduse) põhjal.
- Lihtsa funktsiooni rakendamine igale elemendile.
Kasutusjuhtum 1: Väärtuste vastendamine sõnastikuga
See on map() kõige tavalisem ja tõhusam kasutus. Kujutage ette, et tahame luua laiema "Osakond" veeru meie "Kategooria" veeru põhjal. Saame määratleda vastenduse Pythoni sõnastikus ja kasutada selle rakendamiseks map().
category_to_department = {
'Electronics': 'Technology',
'Accessories': 'Peripherals',
'Audio': 'Technology'
}
df['Department'] = df['Category'].map(category_to_department)
print(df[['Category', 'Department']])
Väljund:
Category Department
0 Electronics Technology
1 Accessories Peripherals
2 Accessories Peripherals
3 Electronics Technology
4 Accessories Peripherals
5 Audio Technology
6 Electronics Technology
7 Accessories Peripherals
Märkige, kui elegantselt see töötab. Iga väärtus "Category" seerias otsitakse üles sõnastikust `category_to_department` ja vastavat väärtust kasutatakse uue "Department" veeru täitmiseks. Kui võtit sõnastikust ei leita, loob map() väärtuse NaN (Not a Number), mis on sageli soovitud käitumine vastendamata kategooriate puhul.
Kasutusjuhtum 2: Funktsiooni rakendamine map() abil
Võite edastada ka funktsiooni (sealhulgas lambda-funktsiooni) meetodile map(). Funktsioon käivitatakse iga elemendi kohta seerias. Loome uue veeru, mis annab meile hinna kirjeldava sildi.
def price_label(price):
if price > 200:
return 'High-Value'
elif price > 50:
return 'Mid-Value'
else:
return 'Low-Value'
df['Price_Label'] = df['Price_USD'].map(price_label)
# Using a lambda function for a simpler task:
# df['Product_Length'] = df['Product'].map(lambda x: len(x))
print(df[['Product', 'Price_USD', 'Price_Label']])
Väljund:
Product Price_USD Price_Label
0 Laptop 1200 High-Value
1 Mouse 25 Low-Value
2 Keyboard 75 Mid-Value
3 Monitor 300 High-Value
4 Webcam 50 Low-Value
5 Headphones 150 Mid-Value
6 Docking Station 250 High-Value
7 Mouse 30 Low-Value
Millal kasutada map(): Kiire kokkuvõte
- Te töötate ühe veeru (Series) kallal.
- Teil on vaja asendada väärtusi sõnastiku või teise seeria (Series) põhjal. See on selle peamine tugevus.
- Teil on vaja rakendada lihtsat elemendipõhist funktsiooni ühele veerule.
Meetod apply(): Mitmekülgne tööhobune
Mis on apply()?
Kui map() on spetsialist, siis apply() on üldotstarbeline jõujaam. See on paindlikum, sest see saab töötada nii seeriate (Series) kui ka andmeraamidega (DataFrames). apply() mõistmise võti on parameeter axis, mis juhib selle toimimist:
- Seerias (Series): See töötab elemendipõhiselt, sarnaselt
map()-le. - Andmeraamis (DataFrame)
axis=0(vaikimisi): See rakendab funktsiooni igale veerule. Funktsioon saab iga veeru seeriana (Series). - Andmeraamis (DataFrame)
axis=1: See rakendab funktsiooni igale reale. Funktsioon saab iga rea seeriana (Series).
apply() seerias (Series)
Seerias (Series) kasutades käitub apply() väga sarnaselt map()-le. See rakendab funktsiooni igale elemendile. Näiteks saaksime korrata meie hinna sildi näidet.
df['Price_Label_apply'] = df['Price_USD'].apply(price_label)
print(df['Price_Label_apply'].equals(df['Price_Label'])) # Output: True
Kuigi need tunduvad siin vahetatavad, on map() sageli veidi kiirem lihtsate sõnastiku asenduste ja elemendipõhiste toimingute puhul seerias (Series), sest sellel on nende spetsiifiliste ülesannete jaoks optimeeritum tee.
apply() andmeraamistikus (veerupõhine, axis=0)
See on DataFrame'i vaikimisi režiim. Teie antud funktsiooni kutsutakse iga veeru kohta üks kord. See on kasulik veerupõhiste agregeerimiste või teisenduste jaoks.
Leiame maksimaalse ja minimaalse väärtuse (vahemiku) erinevuse iga meie numbrilise veeru kohta.
numeric_cols = df[['Price_USD', 'Quantity']]
def get_range(column_series):
return column_series.max() - column_series.min()
column_ranges = numeric_cols.apply(get_range, axis=0)
print(column_ranges)
Väljund:
Price_USD 1175.0
Quantity 2.0
dtype: float64
Siin sai funktsioon get_range esmalt seeria "Price_USD", arvutas selle vahemiku, seejärel sai seeria "Quantity" ja tegi sama, tagastades tulemustega uue seeria.
apply() andmeraamistikus (reahaaval, axis=1)
See on vaieldamatult kõige võimsam ja levinum apply() kasutusjuhtum. Kui teil on vaja arvutada uus väärtus, mis põhineb mitmel veergudel samas reas, on apply() koos axis=1 teie parim lahendus.
Teie edastatud funktsioon saab iga rea seeriana, kus indeksiks on veerunimed. Arvutame iga tellimuse kogukulu.
def calculate_total_cost(row):
# 'row' is a Series representing a single row
price = row['Price_USD']
quantity = row['Quantity']
return price * quantity
df['Total_Cost'] = df.apply(calculate_total_cost, axis=1)
print(df[['Product', 'Price_USD', 'Quantity', 'Total_Cost']])
Väljund:
Product Price_USD Quantity Total_Cost
0 Laptop 1200 1 1200
1 Mouse 25 2 50
2 Keyboard 75 1 75
3 Monitor 300 2 600
4 Webcam 50 1 50
5 Headphones 150 1 150
6 Docking Station 250 1 250
7 Mouse 30 3 90
See on midagi, mida map() lihtsalt teha ei saa, kuna see on piiratud ühe veeruga. Vaatame keerulisemat näidet. Tahame kategoriseerida iga tellimuse saatmisprioriteedi selle kategooria ja riigi alusel.
def assign_shipping_priority(row):
if row['Category'] == 'Electronics' and row['Country'] == 'USA':
return 'High Priority'
elif row['Total_Cost'] > 500:
return 'High Priority'
elif row['Country'] == 'Japan':
return 'Medium Priority'
else:
return 'Standard'
df['Shipping_Priority'] = df.apply(assign_shipping_priority, axis=1)
print(df[['Category', 'Country', 'Total_Cost', 'Shipping_Priority']])
Millal kasutada apply(): Kiire kokkuvõte
- Kui teie loogika sõltub rea mitmest veerust (kasutage
axis=1). See on selle tapjaomadus. - Kui teil on vaja rakendada agregeerimisfunktsiooni veergudele või ridadele.
- Üldotstarbelise funktsioonide rakendamise tööriistana, kui
map()ei sobi.
Eriline märkus: Meetod applymap()
Mis on applymap()?
Meetod applymap() on veel üks spetsialist, kuid selle domeeniks on kogu DataFrame. See rakendab funktsiooni igale üksikule elemendile DataFrame'is. See ei tööta seeria (Series) peal – see on ainult DataFrame'i meetod.
Mõelge sellele kui map() käivitamisele igas veerus samaaegselt. See on kasulik laiaulatuslikeks teisendusteks, näiteks vormindamiseks või tüübiteisenduseks kõigis lahtrites.
DataFrame.applymap() vananenud. Uus soovitatav viis on kasutada DataFrame.map(). Funktsionaalsus on sama. Kasutame siin ühilduvuse huvides applymap(), kuid olge tulevase koodi puhul sellest muudatusest teadlik.
Praktiline näide
Oletame, et meil on alam-DataFrame ainult meie numbriliste veergudega ja me tahame need kõik vormindada valuutastringidena aruande jaoks.
numeric_df = df[['Price_USD', 'Quantity', 'Total_Cost']]
# Using a lambda function to format each number
formatted_df = numeric_df.applymap(lambda x: f'${x:,.2f}')
print(formatted_df)
Väljund:
Price_USD Quantity Total_Cost
0 $1,200.00 $1.00 $1,200.00
1 $25.00 $2.00 $50.00
2 $75.00 $1.00 $75.00
3 $300.00 $2.00 $600.00
4 $50.00 $1.00 $50.00
5 $150.00 $1.00 $150.00
6 $250.00 $1.00 $250.00
7 $30.00 $3.00 $90.00
Teine levinud kasutus on stringandmetega DataFrame'i puhastamine, näiteks kõigi väärtuste teisendamine väiketähtedeks.
string_df = df[['Product', 'Category', 'Country']].copy() # Create a copy to avoid SettingWithCopyWarning
# Ensure all values are strings to prevent errors
string_df = string_df.astype(str)
lower_df = string_df.applymap(str.lower)
print(lower_df)
Millal kasutada applymap(): Kiire kokkuvõte
- Kui teil on vaja rakendada ühte lihtsat funktsiooni igale elemendile DataFrame'is.
- Ülesannete jaoks, nagu andmetüübi teisendamine, stringide vormindamine või lihtsad matemaatilised teisendused kogu DataFrame'is.
- Pidage meeles selle vananemist
DataFrame.map()kasuks uuemates Pandase versioonides.
Jõudluse süvaanalüüs: Vektoriseerimine vs. iteratsioon
"Varjatud" tsükkel
See on kõige kriitilisem kontseptsioon, mida tuleb mõista suure jõudlusega Pandase koodi kirjutamisel. Kuigi apply(), map() ja applymap() on mugavad, on need sisuliselt vaid keerukad ümbrised Pythoni tsükli ümber. Kui kasutate df.apply(..., axis=1), itereerib Pandas teie DataFrame'i rida-realt, edastades iga rea teie funktsioonile. Sellel protsessil on märkimisväärne üldkulu ja see on palju aeglasem kui C-s või Cythonis optimeeritud toimingud.
Vektoriseerimise jõud
Vektoriseerimine on toimingute tegemine tervete massiivide (või seeriate) peal korraga, mitte üksikute elementide peal. Pandas ja selle aluseks olev teek NumPy on spetsiaalselt loodud olema uskumatult kiired vektoriseeritud toimingute puhul.
Vaatame uuesti meie "Total_Cost" arvutust. Kasutasime apply(), kuid kas on olemas vektoriseeritud viis?
# Meetod 1: Kasutades apply() (Iteratsioon)
df['Total_Cost'] = df.apply(lambda row: row['Price_USD'] * row['Quantity'], axis=1)
# Meetod 2: Vektoriseeritud toiming
df['Total_Cost_Vect'] = df['Price_USD'] * df['Quantity']
# Kontrollige, kas tulemused on samad
print(df['Total_Cost'].equals(df['Total_Cost_Vect'])) # Output: True
Teine meetod on vektoriseeritud. See võtab kogu "Price_USD" seeria ja korrutab selle kogu "Quantity" seeriaga ühe, kõrgelt optimeeritud operatsiooniga. Kui te mõõdaksite nende kahe meetodi aega suurel DataFrame'il (miljonid read), ei oleks vektoriseeritud lähenemine mitte ainult kiirem – see oleks suurusjärkude võrra kiirem. Räägime sekunditest minutite vastu või minutitest tundide vastu.
Millal on apply() vältimatu?
Kui vektoriseerimine on nii palju kiirem, miks need teised meetodid eksisteerivad? Sest mõnikord on teie loogika vektoriseerimiseks liiga keeruline. apply() on vajalik ja õige tööriist, kui:
- Keeruline tingimuslik loogika: Teie loogika hõlmab keerukaid `if/elif/else` lauseid, mis sõltuvad mitmest veerust, nagu meie `assign_shipping_priority` näide. Kuigi osa sellest saab saavutada `np.select()` abil, võib see muutuda loetamatuks.
- Välise teegi funktsioonid: Teil on vaja rakendada andmetele funktsiooni välisest teegist. Näiteks georuumilise teegi funktsiooni rakendamine kauguse arvutamiseks laius- ja pikkuskraadide veergude põhjal või loomuliku keele töötlemise teegi (nt NLTK) funktsiooni sentimendianalüüsi tegemiseks tekstiveerus.
- Iteratiivsed protsessid: Antud rea arvutus sõltub eelmises reas arvutatud väärtusest (kuigi see on haruldane ja sageli märk sellest, et vaja on teistsugust andmestruktuuri).
Parim tava: Esiteks vektoriseeri, teiseks apply()
See viib Pandase jõudluse kuldreeglini:
Otsige alati esmalt vektoriseeritud lahendust. Kasutage apply() kui oma võimsat ja paindlikku varuvõimalust, kui vektoriseeritud lahendus pole praktiline või võimalik.
Kokkuvõte ja peamised järeldused: Õige tööriista valimine
Koondame oma teadmised selgeks otsustusraamistikuks. Kohandatud teisendamise ülesandega silmitsi seistes esitage endale need küsimused:
Võrdlustabel
| Meetod | Töötab millega | Toimingu ulatus | Funktsioon saab | Peamine kasutusjuhtum |
|---|---|---|---|---|
| Vektoriseerimine | Seeria (Series), Andmeraam (DataFrame) | Kogu massiiv korraga | Puudub (tegevus on otsene) | Aritmeetilised, loogilised operatsioonid. Kõrgeim jõudlus. |
.map() |
Ainult seeria (Series) | Elemendipõhiselt | Üksik element | Väärtuste asendamine sõnastiku põhjal. |
.apply() |
Seeria (Series), Andmeraam (DataFrame) | Rida-realt või veerg-veerult | Seeria (Series) (rida või veerg) | Keeruline loogika, kasutades rea kohta mitut veergu. |
.applymap() |
Ainult andmeraam (DataFrame) | Elemendipõhiselt | Üksik element | Iga lahtri vormindamine või teisendamine andmeraamis (DataFrame). |
Otsustusvooskeem
- Kas minu toimingut saab väljendada tervete veergude peal põhitehete (+, -, *, /) või loogiliste operaatorite (&, |, ~) abil?
→ Jah? Kasutage vektoriseeritud lähenemist. See on kõige kiirem. (nt `df['col1'] * df['col2']`) - Kas ma töötan ainult ühe veeruga ja kas minu peamine eesmärk on asendada väärtused sõnastiku põhjal?
→ Jah? KasutageSeries.map(). See on selleks optimeeritud. - Kas mul on vaja rakendada funktsiooni igale üksikule elemendile kogu minu DataFrame'is?
→ Jah? KasutageDataFrame.applymap()(võiDataFrame.map()uuemates Pandase versioonides). - Kas minu loogika on keeruline ja nõuab mitme veeru väärtusi igas reas, et arvutada üks tulemus?
→ Jah? KasutageDataFrame.apply(..., axis=1). See on teie tööriist keerulise, reahaaval loogika jaoks.
Järeldus
Kohandatud funktsioonide rakendamise võimaluste navigeerimine Pandas on iga andmespetsialisti jaoks üleminekuriitus. Kuigi need võivad esmapilgul tunduda vahetatavad, on map(), apply() ja applymap() eraldiseisvad tööriistad, millest igaühel on oma tugevused ja ideaalsed kasutusjuhud. Mõistes nende erinevusi, saate kirjutada koodi, mis pole mitte ainult õige, vaid ka loetavam, hooldatavam ja oluliselt jõudlam.
Pidage meeles hierarhiat: eelistage vektoriseerimist selle toore kiiruse pärast, kasutage map() selle tõhusa seeria (Series) asendamise jaoks, valige applymap() DataFrame'i hõlmavate teisenduste jaoks ning kasutage apply() võimsust ja paindlikkust keerulise rea- või veerupõhise loogika jaoks, mida ei saa vektoriseerida. Relvastatud nende teadmistega, olete nüüd paremini varustatud lahendama mis tahes andmetöötlusprobleeme, mis teie teele tulevad, teisendades toorandmed oskuslikult ja tõhusalt võimsateks teadmisteks.